package logmanager.job;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

//classe implementant l'interface DatasMap pour les sources de donn�e fichier texte de log

public class FileLog implements DatasMap{
	private String fileName; //nom de la source de donn�e
	private LogDescription description; //description dans la source de donn�e
	private TextReader textReader; //objet de lecture du fichier
	private int readSize = 100; //nombre de ligne a lire par block par defaut
	private String date = ""; //variable contenant la date lu dans le commentaire qui sera concerver par la suite 
	//mm si la date n'es pas preciser dans la suite
	private int lineReadCount = 0, logSize=0;
	private String minData="", maxDate;

	public FileLog(String fileName) throws FileNotFoundException {
		super();
		this.fileName = fileName;
		description = new LogDescription();
	}

	public FileLog(String fileName, int nbGet) throws FileNotFoundException {
		this(fileName);
		this.readSize = nbGet;
	}

	public void close() throws IOException{
		textReader.close();
	}

	public ArrayList<String> getDataFormatDescription() {
		return description.getFormat();
	}

	public void seek(int nbLine) throws IOException{
		int i=0;
		String line="";
		while (i<nbLine && line!=null) {
			line = textReader.readLine();
			i++;
		}
	}

	public String getMinData(){
		return minData;
	}

	private void getProperties(String field, String filter) throws IOException{
		textReader = new TextReader(fileName);
		String line, elem;
		StringTokenizer stk;
		logSize = 0;
//		System.out.print("getProperties : " + logSize + " ");	//
		line = getNextLine(textReader);
		String []d;
		while(!line.equals("null")){
			if(!line.equals("")){
				if(line.charAt(0) == '#'){
					stk = new StringTokenizer(line.substring(1), " ");
					elem = stk.nextToken();
					if(elem.equals("Start-Date:") || elem.equals("Date:")){
						maxDate = stk.nextToken();
					}
				}else if(line.charAt(0) != '#'){ //une donn�e
					d =	extractData(line, field, filter);
					if(d != null){
						logSize++;
					}
				}
			}
			line = getNextLine(textReader);
		}
//		System.out.println("getProperties : " + logSize);	//
		close();
	}

	public String getMaxDate(){
		return maxDate;
	}

	public int getLogSize() {
		return logSize;
	}

	public String[][] getNextDatas(String field, String value, int position) throws IOException {
		textReader = new TextReader(fileName);
		seek(position);
		String line;
		String[][] data = new String[readSize][];
		int type, i=0,k=0, maxLength=0;
		while(i<readSize){
			line = getNextLine(textReader);
			if(line.equals("")){
				k++;
				continue;
			}
			if(line.equals("null")){ // fin du fichier
				data = complete(data, maxLength, i);
				i = readSize+1;
				lineReadCount = k;
				close();
				getProperties(field, value);
				return data;
			}
			type = TypeLine(line);
			if(type == 1){ //c'est un commentaire
				treatComment(line.substring(1));
				k++;
			}else if(type == 0){ //une donn�e
				k++;
				data[i] = extractData(line, field, value);
				if(data[i] == null)
					continue;
				maxLength = (maxLength<data[i].length)?data[i].length:maxLength;
				i++;
			}
		}
		lineReadCount = k;
		data = complete(data, maxLength, i);
		close();
		getProperties(field, value);
		return data;
	}

//s'assurer du m�me nombre de champs pour chaque ligne m�me si tel n'es pas le cas ds le fichier
	private String[][] complete(String [][] data, int len, int nbRows){
		String[] d;
		String [][] dd = new String[nbRows][];
		for (int i = 0; i < dd.length; i++) {
			d = new String[len];
			for (int j = 0; j < data[i].length; j++) {
				d[j] = data[i][j];
			}
			if(data[i].length<len){
				for (int j = data[i].length; j < len; j++) {
					d[j] = "";
				}
			}
			dd[i] = d;
		}
		return dd;
	}

	//extraction des donn�e d'une ligne soit avec un filtrage (="" si pas de filtrage)
	private String [] extractData(String data, String field, String filter){
		if(field.equals(""))
			if(data.toLowerCase().indexOf(filter) < 0 && date.toLowerCase().indexOf(filter) <0)
				return null;
		int nb = getDescription().getFormat().size();
		String [] datass = new String[nb]; //normalement nb
		for (int i = 0; i < datass.length; i++) {
			datass[i] = "";
		}
		StringTokenizer stk = new StringTokenizer(data, "	");
		datass[0] = date;

		for(int i=0; i<getDescription().getDescription().size(); i++){
			datass[description.getDescription().get(i)] = stk.nextToken();
		}
		if(!field.equals(""))
			if(datass[description.get(field)].toLowerCase().indexOf(filter) < 0)
				return null;
		return datass;
	}

	//traitement du commentaire bien (pr�cison des champs)
	private void treatComment(String comm){
		StringTokenizer stk = new StringTokenizer(comm, " ");
		String elem = stk.nextToken();
		boolean end=false;
		if(elem.equals("Start-Date:") || elem.equals("Date:")){
			elem = stk.nextToken();
			if(minData.equals("")){
				minData = elem;
			}
			date = elem;
		}else if(elem.equals("Fields:")){	
			description.init();
			//description.addDescription(0);
			if(description.getFormat().size() < description.getDescription().size())
				description.addFormat("date");
			elem = stk.nextToken();
			while(!end){
				try {
					orderField(elem);
					elem = stk.nextToken();
				}catch (Exception e) {
					end = true;
				}
			}
		}
	}

	//donn�e en sorti le bon ordre des champs 
	private void orderField(String elem){
		int pos;
		if(description.getFormat().contains(elem)){
			pos = description.getFormat().indexOf(elem);
			description.addDescription(pos);
		}else{
			description.addFormat(elem);
			description.addDescription(description.getFormat().size()-1);
		}
	}

	//retourne le type de la ligne (commentaire ou donn�e)
	private int TypeLine(String line){
		if (line.charAt(0) == '#')
			return 1;
		return 0;
	}

	//lit le ligne suivant dans le fichier
	public String getNextLine(TextReader tr) throws IOException{
		return tr.readLine();
	}

	public int getReadSize() {
		return readSize;
	}
	public void setReadSize(int readSize) {
		this.readSize = readSize;
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	//recuc�per l'objet de description 
	public LogDescription getDescription() {
		return description;
	}

	//imposer un objet de description
	public void setDescription(LogDescription description) {
		this.description = description;
	}
	public int rowsCount() {
		return description.getDescription().size();
	}
	public int getLineReadCount() {
		return lineReadCount;
	}
}
